package com.landmesure.settings.fragment.tree;

import com.landmesure.settings.fragment.argsinfo.ArgumentsInfo;

import java.util.ArrayList;

@SuppressWarnings("unchecked")
public class TypeTree implements Cloneable {
    private ArrayList<TypeTreeNote> mRoots;    //根节点
    private ArrayList<TypeTreeNote> mParents;    //父节点
    private ArrayList<TypeTreeNote> mLeafs;    //叶子节点

    private ArrayList<TypeTreeNote> mNotes = new ArrayList<>();    //存储同一父节点的叶子节点;

    private ArrayList<TypeTreeNote> mAllNotes = new ArrayList<>();    //所有节点集合
    private ArrayList<String> mAllNotesName = new ArrayList<>();

    public TypeTree() { }

    /**
     * 创建节点
     */
    public TypeTree addNote(int id, int pid, int level, String name,
                            ArrayList<ArgumentsInfo> argumentsInfos) {
        mNotes.add(new TypeTreeNote(name, id, pid, level, argumentsInfos)
                .setParentNote(null)
                .setChildNote(null));
        return this;
    }

    /**
     * 设置根节点
     */
    public void setRootNote(ArrayList<TypeTreeNote> notes) {
        if (null == notes || notes.isEmpty()) {
            return;
        }
        for (TypeTreeNote note : notes) {
            note.setParentNote(null).setChildNote(null);
        }
        mRoots = notes;
        mParents = mRoots;
    }

    /**
     * 直接根据节点列表创建树
     * @param noteArrayList 所有节点集合，逐层分布，包含子节点与父节点的关系
     * @return 树的根目录
     */
    public ArrayList<TypeTreeNote> buildTree(ArrayList<TypeTreeNote> noteArrayList) {
        if (null == noteArrayList || noteArrayList.isEmpty()) {
            return null;
        }
        boolean isgo;
        final int size = noteArrayList.size();
        ArrayList<TypeTreeNote> roots = new ArrayList<>();    //根节点
        ArrayList<ArrayList<TypeTreeNote>> notes;    //记录子节点
        ArrayList<TypeTreeNote> childs = new ArrayList<>();    //子节点集合
        ArrayList<TypeTreeNote> parents = new ArrayList<>();    //父节点
        ArrayList<ArrayList<TypeTreeNote>> leafs = new ArrayList<>();     //同一层的叶子节点集合
        initList(leafs, size);

        TypeTreeNote note;
        for (int i = 0; i < size; i++) {
            note = noteArrayList.get(i);
            if (0 > note.getPid()) {
                roots.add(note);
                parents = roots;
                continue;
            }
            int p = 0;
            isgo = assist(parents, note, leafs, childs);
            if (!isgo) {
                notes = (ArrayList<ArrayList<TypeTreeNote>>) leafs.clone();
                for (TypeTreeNote ttn : parents) {
                    ttn.setChildNote(notes.get(p));
                    p++;
                }
                p = 0;
                leafs.clear();
                initList(leafs, size);
                parents = (ArrayList<TypeTreeNote>) childs.clone();
                childs.clear();
                assist(parents, note, leafs, childs);
            }
            if (size - 1 == i) {
                for (TypeTreeNote ttn : parents) {
                    ttn.setChildNote(leafs.get(p));
                    p++;
                }
            }
        }

        return roots;
    }

    private void initList(ArrayList<ArrayList<TypeTreeNote>> lists, final int size) {
        for (int i = 0; i < size; i++) {
            lists.add(new ArrayList<TypeTreeNote>());
        }
    }

    private boolean assist(ArrayList<TypeTreeNote> parents, TypeTreeNote note,
                        ArrayList<ArrayList<TypeTreeNote>> leafs, ArrayList<TypeTreeNote> childs) {
        int p = 0;
        boolean isgo = false;
        for (TypeTreeNote ttn : parents) {
            if (note.getPid() == ttn.getId()) {
                note.setParentNote(ttn);
                leafs.get(p).add(note);
                childs.add(note);
                isgo = true;
            }
            p++;
        }
        return isgo;
    }

    /**
     *创建一层树，入参为对应层的叶子
     */
    public void createTree(ArrayList<TypeTreeNote> leafs) {
        if (null == leafs || leafs.isEmpty()
                || null == mParents || mParents.isEmpty()) {
            return;
        }
        mLeafs = leafs;

        int i = 0;
        TypeTreeNote parent = mParents.get(i);
        ArrayList<TypeTreeNote> leafList = new ArrayList<>();
        TypeTreeNote leaf = null;
        final int size = mLeafs.size();
        for (int m = 0; m <= size; m++ ) {
            if (m < size) {
                leaf = mLeafs.get(m);
                if (parent.getId() == leaf.getPid()) {
                    treeConnect(parent, leaf, leafList);
                    continue;
                }
            }
            ArrayList<TypeTreeNote> leafCommon =
                    (ArrayList<TypeTreeNote>) leafList.clone();
            parent.setChildNote(leafCommon);
            leafList.clear();
            if (m == size) {
                break;
            }
            i++;
            if (i < mParents.size()) {
                parent = mParents.get(i);
                treeConnect(parent, leaf, leafList);
            }
        }

        mParents = mLeafs;
    }

    private void treeConnect(TypeTreeNote parent, TypeTreeNote leaf,
                             ArrayList<TypeTreeNote> leafList) {
        leaf.setParentNote(parent);
        leaf.setChildNote(null);
        leafList.add(leaf);
    }

    /**
     * 逐层遍历树
     */
    public void traversalTree(ArrayList<TypeTreeNote> parents) {
        if (null == parents || parents.isEmpty()) {
            return;
        }
        ArrayList<TypeTreeNote> childs;
        for (TypeTreeNote note : parents) {
            mAllNotes.add(note);
            childs = note.getChildNotes();
            if (null != childs) {
                traversalTree(childs);
            }
        }
    }

    public ArrayList<TypeTreeNote> getNotes() {
        ArrayList<TypeTreeNote> notes = (ArrayList<TypeTreeNote>) mNotes.clone();
        mNotes.clear();
        return notes;
    }

    public ArrayList<TypeTreeNote> getRoots() {
        return mRoots;
    }

    public ArrayList<TypeTreeNote> getAllNotes() {
        return mAllNotes;
    }

    public ArrayList<String> getAllNotesName() {
        ArrayList<ArgumentsInfo> infos;
        ArgumentsInfo info;
        for (TypeTreeNote note : mAllNotes) {
            infos = note.getArgumentsInfos();
            if (null != infos && !infos.isEmpty()) {
                info = infos.get(0);
                if (null != info) {
                    mAllNotesName.add(note.getName() + "<-->"+ info.mPropName);
                }
            }
        }
        return mAllNotesName;
    }

    @Override
    public Object clone() {
        TypeTree typeTreeClone = null;
        try {
            typeTreeClone = (TypeTree) super.clone();
            typeTreeClone.mAllNotes = (ArrayList<TypeTreeNote>) this.mAllNotes.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return typeTreeClone;
    }
}
